package com.ikun.admin.modules.gen.iservice.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ikun.admin.common.constant.CommonCharactersConstant;
import com.ikun.admin.modules.gen.iservice.IMenuService;
import com.ikun.admin.modules.gen.vo.MenuAddOrUpdateVo;
import com.ikun.admin.modules.gen.vo.MenuDictVo;
import com.ikun.admin.modules.gen.vo.MenuTreeVo;
import com.ikun.admin.modules.sys.entity.Menu;
import com.ikun.admin.modules.sys.entity.RoleMenu;
import com.ikun.admin.modules.sys.service.MenuService;
import com.ikun.admin.modules.sys.service.RoleMenuService;
import com.ikun.common.exception.MyException;
import com.ikun.common.result.Result;
import com.ikun.common.tree.TreeUtil;
import com.ikun.common.utils.DataCopy;
import com.ikun.common.validate.validator.ValidateExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName IMenuServiceImpl
 * @Description:
 * @CreateDate: 2024/8/12 23:23
 */
@Service
public class IMenuServiceImpl implements IMenuService {
    private static final Integer MENU_TYPE_MENU = 0;
    private static final Integer MENU_TYPE_PERM = 1;
    private static final Integer MENU_IF_DEV = 0;
    private static final Integer MENU_NOT_DEV = 1;

    @Autowired
    private MenuService menuService;

    @Autowired
    private RoleMenuService roleMenuService;

    @Override
    public Result<List<MenuTreeVo>> menuTree() {
        List<Menu> menuList = menuService.list(new QueryWrapper<>());
        List<MenuTreeVo> menuTreeVoList = DataCopy.copyToListObj(menuList, MenuTreeVo.class);
        List<MenuTreeVo> build = TreeUtil.build(menuTreeVoList);
        return new Result<List<MenuTreeVo>>().success(build);
    }

    @Override
    public Result<MenuAddOrUpdateVo> menuDetail(Long id) {
        Menu menu = menuService.getById(id);
        MenuAddOrUpdateVo menuAddOrUpdateVo = DataCopy.copyToObj(menu, MenuAddOrUpdateVo.class);
        return new Result<MenuAddOrUpdateVo>().success(menuAddOrUpdateVo);
    }

    private void validate(Menu menu) {
       if(menu.getType() == MENU_TYPE_PERM) {
            if (menu.getPerm() == null || !CommonCharactersConstant.REGEX3.matches(menu.getPerm())) {
                throw new MyException("权限路径,示例:xxx:yyy");
            }
        }
    }

    @Override
    @Transactional
    public Result<String> addOrUpdateMenu(MenuAddOrUpdateVo menuAddOrUpdateVo) {
        ValidateExecutor.execute(menuAddOrUpdateVo, null);
        Menu menu = DataCopy.copyToObj(menuAddOrUpdateVo, Menu.class);
        this.validate(menu);
        if (menuAddOrUpdateVo.getId() == null) {
            menuService.save(menu);
        } else {
            //编辑
            menuService.updateById(menu);
        }
        return new Result<String>().success("操作成功");
    }

    @Override
    @Transactional
    public Result<String> menuDelete(Long id) {
        List<Menu> list = menuService.list(new QueryWrapper<Menu>().lambda().eq(Menu::getPid, id).eq(Menu::getType, MENU_TYPE_MENU));
        if (list.size() > 0) {
            throw new MyException("该菜单下有子菜单，无法删除");
        }
        menuService.removeById(id);
        List<Menu> permList = menuService.list(new QueryWrapper<Menu>().lambda().eq(Menu::getPid, id).eq(Menu::getType, MENU_TYPE_PERM));
        List<Long> permIdList = new ArrayList<>();
        if (permList.size() > 0) {
            permIdList = permList.stream().map(Menu::getId).collect(Collectors.toList());
            menuService.removeByIds(permIdList);
        }
        permIdList.add(id);
        roleMenuService.remove(new QueryWrapper<RoleMenu>().lambda().in(RoleMenu::getMenuId, permIdList));
        return new Result<String>().success("操作成功");
    }

    @Override
    public Result<List<MenuDictVo>> menuDictList(Integer type) {
        LambdaQueryWrapper<Menu> queryWrapper = new QueryWrapper<Menu>().lambda().eq(Menu::getType, MENU_TYPE_MENU);
        if (type == MENU_TYPE_MENU) {
            queryWrapper.isNull(Menu::getRouter);
        } else {
            queryWrapper.isNotNull(Menu::getRouter);
        }
        List<Menu> menuList = menuService.list(queryWrapper);
        List<MenuDictVo> menuDictVoList = DataCopy.copyToListObj(menuList, MenuDictVo.class);
        List<MenuDictVo> treeList = type == MENU_TYPE_MENU ? TreeUtil.build(menuDictVoList) : menuDictVoList;
        return new Result<List<MenuDictVo>>().success(treeList);
    }
}
